/**
 * unit，该工具包依赖 golang 时间包封装各种方便于实际使用的时间相关工具方法
 * 创建者：Bryce
 * 创建时间：20210901
 */
package unit

import "time"

/**
 * UniqueIntSlice，计算指定时间属于当前年的第几周
 * Params：
 *   t：指定时间信息
 * Return：
 *   当前年的周数
 */
func ByTimeGetWeek(t time.Time) int {
	yearDay := t.YearDay()
	yearFirstDay := t.AddDate(0, 0, -yearDay+1)
	firstDayInWeek := int(yearFirstDay.Weekday())

	// 今年第一周有几天
	firstWeekDays := 1
	if firstDayInWeek != 0 {
		firstWeekDays = 7 - firstDayInWeek + 1
	}

	var week int
	if yearDay <= firstWeekDays {
		week = 1
	} else {
		week = (yearDay-firstWeekDays)/7 + 2
	}

	return week
}

/**
 * GetWeekDay，获取指定时间所属周的开始和结束时间
 * Params：
 *   t：指定时间信息
 * Return：
 *   当前周的周一开始时间
 *   当前周的周日结束时间
 */
func ByTimeGetWeekDay(t time.Time) (string, string) {
	offset := int(time.Monday - t.Weekday())
	if offset > 0 { // 周日做特殊判断 因为time.Monday = 0
		offset = -6
	}

	lastOffset := int(time.Saturday - t.Weekday())
	if lastOffset == 6 { // 周日做特殊判断 因为time.Monday = 0
		lastOffset = -1
	}

	firstOfWeek := time.Date(t.Year(), t.Month(), t.Day(), 0, 0, 0, 0, time.Local).AddDate(0, 0, offset)
	lastOfWeeK := time.Date(t.Year(), t.Month(), t.Day(), 0, 0, 0, 0, time.Local).AddDate(0, 0, lastOffset+1)
	f := firstOfWeek.Unix()
	l := lastOfWeeK.Unix()
	return time.Unix(f, 0).Format("2006-01-02") + " 00:00:00", time.Unix(l, 0).Format("2006-01-02") + " 23:59:59"
}

/**
 * GetMonthDay，获得指定时间所属月份的初始和结束日期时间
 * Params：
 *   t：指定时间信息
 * Return：
 *   当前月的第一天开始时间
 *   当前月的最后一天结束时间
 */
func ByTimeGetMonthDay(t time.Time) (string, string) {
	currentYear, currentMonth, _ := t.Date()
	currentLocation := t.Location()

	firstOfMonth := time.Date(currentYear, currentMonth, 1, 0, 0, 0, 0, currentLocation)
	lastOfMonth := firstOfMonth.AddDate(0, 1, -1)
	f := firstOfMonth.Unix()
	l := lastOfMonth.Unix()
	return time.Unix(f, 0).Format("2006-01-02") + " 00:00:00", time.Unix(l, 0).Format("2006-01-02") + " 23:59:59"
}

/**
 * GetQuarterDay，获得指定时间所属季度的初始和结束日期时间
 * Params：
 *   t：指定时间信息
 * Return：
 *   季度的第一天开始时间
 *   季度的最后一天结束时间
 */
func ByTimeGetQuarterDay(t time.Time) (string, string) {
	year := t.Format("2006")
	month := int(t.Month())
	var firstOfQuarter string
	var lastOfQuarter string
	if month >= 1 && month <= 3 {
		//1月1号
		firstOfQuarter = year + "-01-01 00:00:00"
		lastOfQuarter = year + "-03-31 23:59:59"
	} else if month >= 4 && month <= 6 {
		firstOfQuarter = year + "-04-01 00:00:00"
		lastOfQuarter = year + "-06-30 23:59:59"
	} else if month >= 7 && month <= 9 {
		firstOfQuarter = year + "-07-01 00:00:00"
		lastOfQuarter = year + "-09-30 23:59:59"
	} else {
		firstOfQuarter = year + "-10-01 00:00:00"
		lastOfQuarter = year + "-12-31 23:59:59"
	}
	return firstOfQuarter, lastOfQuarter
}

/**
 * GetBetweenDates，获得指定日时间段内的日期列表
 * Params：
 *   startDate：指定开始日期，如：2021-11-21
 *   endDate：指定结束日期，如：2021-12-11
 * Return：
 *   日期列表
 */
func ByTimeGetBetweenDates(startDate, endDate string) []string {
	d := make([]string, 0)
	timeFormatTpl := "2006-01-02 15:04:05"
	if len(timeFormatTpl) != len(startDate) {
		timeFormatTpl = timeFormatTpl[0:len(startDate)]
	}
	date, err := time.Parse(timeFormatTpl, startDate)
	if err != nil { // 时间解析，异常
		return d
	}
	date2, err := time.Parse(timeFormatTpl, endDate)
	if err != nil {
		// 时间解析，异常
		return d
	}
	if date2.Before(date) {
		// 如果结束时间小于开始时间，异常
		return d
	}
	// 输出日期格式固定
	timeFormatTpl = "2006-01-02"
	date2Str := date2.Format(timeFormatTpl)
	d = append(d, date.Format(timeFormatTpl))
	for {
		date = date.AddDate(0, 0, 1)
		dateStr := date.Format(timeFormatTpl)
		d = append(d, dateStr)
		if dateStr == date2Str {
			break
		}
	}
	return d
}

/**
 * DateToTime，格式化时间转时间戳
 * Params：
 *   date：格式化时间
 *   other：第一位：时区信息，默认 UTC 时区；第二位：转换格式，默认"2006-01-02 15:04:05"。
 * Return：
 *   时间戳
 */
func DateToTime(date string, other ...string) (int64, error) {
	// 设置默认值
	zone := "UTC"
	format := "2006-01-02 15:04:05"
	if len(other) == 1 {
		zone = other[0]
	} else if len(other) >= 2 {
		zone = other[0]
		format = other[1]
	}
	// 设置时区
	loc, err := time.LoadLocation(zone)
	if err != nil {
		return 0, err
	}
	// 设置转换格式
	tt, err := time.ParseInLocation(format, date, loc)
	if err != nil {
		return 0, err
	}
	return tt.Unix(), nil
}

/**
 * TimeToDate，时间戳转格式化时间
 * Params：
 *   time：时间戳
 *   other：第一位：转换格式，默认 "2006-01-02 15:04:05"
 * Return：
 *   日期时间
 */
func TimeToDate(t int64, other ...string) string {
	format := "2006-01-02 15:04:05"
	if len(other) > 0 {
		format = other[0]
	}
	return time.Unix(t, 0).Format(format)
}
